package com.shfl.task.component;

import com.shfl.task.logic.bean.TaskJob;
import com.shfl.task.logic.service.TaskJobInitService;
import org.quartz.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.lang.NonNull;
import org.springframework.scheduling.quartz.CronTriggerFactoryBean;
import org.springframework.scheduling.quartz.MethodInvokingJobDetailFactoryBean;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;

import java.text.ParseException;
import java.util.*;

@Component
public class InitComponent {

    @Autowired
    private TaskJobInitService taskJobService;

    @Autowired
    private RemoteComponent remoteComponent;

    /**
     * 数据库获取开启的调度
     *
     * @return 调度的任务数据
     */
    public CronTrigger[] getCronTriggers() {
        Map<String, Object> objectMap = new HashMap<>();
        objectMap.put("jobStatus", 0);
        // 数据库获取任务
        List<TaskJob> taskJobList = taskJobService.findListByMap(objectMap);
        List<CronTrigger> cronTriggers = new ArrayList<>();
        if (!CollectionUtils.isEmpty(taskJobList)) {
            for (TaskJob taskJob : taskJobList) {
                try {
                    cronTriggers.add(intCronTriggerFactoryBean(taskJob, intMethodInvokingJobDetailFactoryBean(taskJob)).getObject());
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }
        return cronTriggers.toArray(new CronTrigger[0]);
    }


    public void startJob(TaskJob taskJob, Scheduler scheduler) throws Exception {
        // 定义任务
        JobDetail jobDetail = JobBuilder
                .newJob(getClass(taskJob.getJobUrl()))
                .withIdentity(taskJob.getJobName(), taskJob.getJobGroup()).build();
        JobDataMap jobDataMap = new JobDataMap();
        jobDataMap.put("jobDetail", jobDetail);
        // 定义触发器
        CronScheduleBuilder scheduleBuilder = CronScheduleBuilder.cronSchedule(taskJob.getJobCron());
        CronTrigger cronTrigger = TriggerBuilder.newTrigger().withIdentity(taskJob.getJobName(), taskJob.getJobGroup())
                .withSchedule(scheduleBuilder).usingJobData(jobDataMap).build();
        scheduler.scheduleJob(jobDetail, cronTrigger);
    }

    public MethodInvokingJobDetailFactoryBean intMethodInvokingJobDetailFactoryBean(@NonNull TaskJob taskJob)
            throws ClassNotFoundException, IllegalAccessException, InstantiationException, NoSuchMethodException {
        MethodInvokingJobDetailFactoryBean jobDetail = new MethodInvokingJobDetailFactoryBean();
        // 如果此处为true，则下一个任务会执行，如果此处为false，则下一个任务会等待上一个任务执行完后，再开始执行
        // 控制并发
        jobDetail.setConcurrent(false);
        jobDetail.setName(taskJob.getJobName());
        jobDetail.setGroup(taskJob.getJobGroup());
        if (Objects.equals((byte) 1, taskJob.getJobType())) {
            jobDetail.setTargetObject(new RemoteTaskComponent(remoteComponent));
            jobDetail.setTargetMethod("task");
            jobDetail.setArguments(new SendInfo(taskJob.getJobUrl()));
        } else {
            Class zlass = Class.forName(taskJob.getJobUrl());
            jobDetail.setTargetObject(zlass.newInstance());
            jobDetail.setTargetMethod(taskJob.getJobMethod());
            if (StringUtils.hasLength(taskJob.getJobArguments())) {
                jobDetail.setArguments(taskJob.getJobArguments());
            }
        }
        jobDetail.afterPropertiesSet();
        return jobDetail;
    }

    public CronTriggerFactoryBean intCronTriggerFactoryBean(
            @NonNull TaskJob taskJob
            , @NonNull MethodInvokingJobDetailFactoryBean jobDetail) throws ParseException {
        CronTriggerFactoryBean trigger = new CronTriggerFactoryBean();
        trigger.setJobDetail(jobDetail.getObject());
        //初始化的cron表达式
        trigger.setCronExpression(taskJob.getJobCron());
        //trigger的name
        trigger.setName(String.valueOf(taskJob.getId()));
        trigger.setGroup(taskJob.getJobGroup());
        trigger.afterPropertiesSet();
        return trigger;
    }

    /**
     * 获取指定字符串的class
     * 因为定时任务中要求的是一个泛型是job类型的class,只有job类型的对象才会有这个class,所以先实例化对象,强转成job,然后再重新获取class
     *
     * @param jobClassName jobClassName
     * @return
     */
    public static Class<? extends Job> getClass(String jobClassName) throws ClassNotFoundException, IllegalAccessException, InstantiationException {
        Class<?> aClass = Class.forName(jobClassName);
        Class<? extends Job> aClass1 = ((Job) aClass.newInstance()).getClass();
        return aClass1;
    }

}
